package customs

import (
    "time"
	"strings"
	"crypto/tls"
	"wxsdk/wxpay/utils/pay"
	"github.com/pkg/errors"
	"github.com/astaxie/beego"
	"github.com/sbabiv/xml2map"
)

type Auth struct {
	reqUrl     string
	appId      string
	mchId      string
	appSecret  string
	TlsConfig  *tls.Config
	Timeout    time.Duration
}

// 海关基础返回数据
type CustomsBaseResponse struct {
	ReturnCode string   `xml:"return_code"`
	ReturnMsg  string   `xml:"return_msg,omitempty"`
	AppId      string   `xml:"appid,omitempty"`        // 微信分配的小程序ID
	MchId      string   `xml:"mch_id,omitempty"`       // 商户号
	Sign       string   `xml:"sign"`                   // 签名
	SignType   string   `xml:"sign_type,omitempty"`    // 签名类型(只有notify通知结果有此项)
	ResultCode string   `xml:"result_code"`            // 业务结果
	ErrCode    string   `xml:"err_code,omitempty"`     // 错误码
	ErrCodeDes string   `xml:"err_code_des,omitempty"` // 错误描述
}

func NewSDK(restURL,appId,mchId,appsecret string,tlsConfig *tls.Config) *Auth {
	return &Auth{reqUrl:restURL,
	             appId:appId,
				 mchId:mchId,
				 appSecret:appsecret,
				 TlsConfig:tlsConfig,
				 Timeout:6}
}

func (this *Auth) request(params map[string]interface{}) (map[string]interface{}, error) {
	//params["appid"] = this.appId
	//params["mch_id"] = this.mchId
	params["sign"] = payutils.MakeSign(params, this.appSecret)
	xmlString := payutils.Map2Xml(params)
	beego.Debug("customs req xml:", xmlString)
	body, err := payutils.SendXmlRequest("POST", this.reqUrl, xmlString, this.TlsConfig, this.Timeout)
	if err != nil {
		return map[string]interface{}{}, err
	}
	beego.Debug("customs rsp xml:", string(body))
	decoder := xml2map.NewDecoder(strings.NewReader(string(body)))
	result, err := decoder.Decode()
	if err != nil {
	   return map[string]interface{}{}, err
	}
	rspMap :=  result["xml"].(map[string]interface{})
	if rspMap["return_code"] != "SUCCESS" {
	    returnMsg := rspMap["return_msg"].(string)
		return map[string]interface{}{}, errors.New(returnMsg)
	}
	if rspMap["result_code"] != "SUCCESS" {
	    errCodeDes := rspMap["err_code_des"].(string)
		return map[string]interface{}{}, errors.New(errCodeDes)
	}
	// 校验回执签名
	sign := payutils.MakeSign(rspMap, this.appSecret)
	if rspMap["sign"] != sign {
		err = errors.New("response sign err")
		return map[string]interface{}{}, err
	}
	return rspMap,nil
}

func (this *Auth) Execute(params map[string]interface{}) (respMap map[string]interface{}, err error) {
	respMap, err = this.request(params)
	return
}
